Bài 14. Hashtable

Liên hệ QC

befaint

|||||||||||||
Tham gia
6/1/11
Bài viết
14,369
Được thích
19,329
Bài 14. Hashtable

(Danh sách các bài viết về VBA xem ở đây Index - Các bài viết về VBA)

Hashtable là một thư viện nằm trong “System.Collections” của .NET Framework. Cho phép lưu trữ dữ liệu ở dạng mảng với Key riêng duy nhất, cho phép chèn và tìm kiếm đối tượng (Item) rất nhanh, kể cả với dữ liệu có kích cỡ lớn.
Yêu cầu: Hệ thống phải cài đặt .NET Framework.

1. Khai báo Hashtable
1.1. Kiểu khai báo sớm
(Không có Tooltip khi gọi Hashtable, phải thiết lập trong Tools/References)
- Trong cửa sổ VBA, Tools menu, References.
- Tìm và check vào mục “mscorlib.dll” trong cửa sổ References – VBAProject.
Khai báo trong code:
PHP:
Dim HTbl As New Hashtable
upload_2017-9-7_1-44-9.png

1.2. Kiểu khai báo muộn
(Không có Tooltip khi gọi Hashtable, không cần thiết lập trong Tools/References).
Khai báo trong code:
PHP:
Dim HTbl As Object
Set HTbl = CreateObject("System.Collections.Hashtable")

2. Các phương thức
2.1. Add
PHP:
HTbl.Add Key, Item
Thêm một Item vào Hashtable.
Key: Bắt buộc. Key nhận kiểu dữ liệu là số hoặc chuỗi bất kỳ. Yêu cầu Key phải duy nhất trong Hashtable, nếu Key đó đã tồn tại thì xảy ra lỗi.
Item: Bắt buộc. Item nhận kiểu dữ liệu là số hoặc chuỗi bất kỳ, giá trị đơn hoặc một mảng (array).
Ví dụ:
PHP:
Sub AddMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.Add Key, Item'
    'Key: number + string, Duy nhat. Gap loi khi Key da ton tai trong HTbl'
    'Item: number + string'
    HTbl.Add 10, 100
    HTbl.Add "KeyA", 200
    HTbl.Add "KeyB", "TextB"
    HTbl.Add 20, 5
    HTbl.Add "KeyC", ""
    HTbl.Add "KeyD", Array(20, 25)
End Sub

2.2. Count
PHP:
HTbl.Count
Trả về số Items có trong Hashtable.
Ví dụ:
PHP:
Sub CountMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.Count'
    Dim i As Long
    For i = 1 To 10
        HTbl.Add "Key" & i, i
    Next i
    MsgBox HTbl.Count '10'
End Sub

2.3. Item
PHP:
HTbl.Item (Key)
'Hoặc:'
HTbl(Key)
Gọi tới Item của Hashtable theo Key chỉ định.
Nếu Key chỉ định đưa vào chưa tồn tại trong Hashtable thì không xảy ra lỗi và kết quả trả về là rỗng.
Ví dụ:
PHP:
Sub ItemMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.Item(Key)'
    'HTbl(Key)'
    HTbl.Add 10, 100
    HTbl.Add "KeyA", 200
    HTbl("KeyA") = 500
    MsgBox HTbl.Item(10)        '100'
    MsgBox HTbl.Item("KeyA")    '500'
End Sub

2.4. Remove
PHP:
HTbl.Remove(Key)
Xóa một Item trong Hashtable theo Key chỉ định ứng với Item đó.
Ví dụ:
PHP:
Sub RemoveMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.Remove(Key)'
    Dim i As Long
    For i = 1 To 10
        HTbl.Add "Key" & i, i
    Next i
    HTbl.Remove ("Key4")
    MsgBox HTbl.Count   '9'
End Sub

2.5. ContainsKey
PHP:
HTbl.ContainsKey(Key)
Kiểm tra sự tồn tại của một Key trong Hashtable. Trả về True nếu Key đó tồn tại, ngược lại trả về False.
Ví dụ:
PHP:
Sub ContainsKeyMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.ContainsKey(Key)'
    HTbl.Add 10, 100
    HTbl.Add "KeyA", 200
    MsgBox HTbl.Containskey(10)     'True'
    MsgBox HTbl.Containskey("KeyA") 'True'
    MsgBox HTbl.Containskey("KeyX") 'False'
End Sub

2.6. ContainsValue
PHP:
HTbl.ContainsValue(Value)
Kiểm tra sự tồn tại giá trị của Item trong Hashtable. Trả về True nếu giá trị đó đã tồn tại, ngược lại trả về False.
Ví dụ:
PHP:
Sub ContainsValueMethod()
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    'HTbl.ContainsValue(Value)'
    HTbl.Add 10, 100
    HTbl.Add "KeyA", "TextA"
    MsgBox HTbl.ContainsValue(100)     'True'
    MsgBox HTbl.ContainsValue("TextA") 'True'
    MsgBox HTbl.ContainsValue("TextB") 'False'
End Sub

3. Ứng dụng
- Lọc loại trùng
- …
3.1. Hàm lọc loại trùng trong một cột

PHP:
'// Loc loai trung mot cot'
Public Function UniqueColumnHashtable(ByVal Rng As Range) As Variant
    If Rng.Count = 1 Then UniqueColumnHashtable = Rng.Value: Exit Function
    Dim HTbl As Object, i As Long, j As Long, arr(), Result(), sKey As Variant
    Set HTbl = CreateObject("System.Collections.Hashtable")
    arr = Rng.Value
    For i = LBound(arr, 1) To UBound(arr, 1)
        sKey = arr(i, 1)
        If sKey <> "" Then
            If HTbl.Containskey(sKey) = False Then
                HTbl.Add sKey, ""
                j = j + 1
                ReDim Preserve Result(1 To j)
                Result(j) = sKey
            End If
        End If
    Next i
    UniqueColumnHashtable = Result
End Function
 

File đính kèm

  • Hashtable.xlsb
    1.2 MB · Đọc: 79
Lần chỉnh sửa cuối:
Bài ví dụ cụ thể áp dụng Hashtable.

1. Ví dụ 1: Lọc loại trùng và tính tổng số lượng ứng với mã sau khi lọc loại trùng.
Xét vùng dữ liệu 100,000 dòng (xem trong file đính kèm ở ngay bài trên).
Sử dụng Hashtable và Dictionay để so sánh.
Hashtable:
PHP:
Sub HashtableFilter()
Dim TT As Double
TT = Timer
Dim HTbl As Object
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
Set HTbl = CreateObject("System.Collections.Hashtable")
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If HTbl.Containskey(sKey) = False Then
                j = j + 1
                HTbl.Add sKey, j
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(HTbl.Item(sKey), 4) = Result(HTbl.Item(sKey), 4) + ArrData(i, 3)
             End If
        End If
    Next i
    If j > 0 Then
        .Range("M2").Resize(100, 4).ClearContents
        .Range("M2").Resize(j, 4) = Result
    End If
End With

MsgBox Round(Timer - TT, 2) '1.62-1.66 giây'
End Sub
Dictionay:
PHP:
Sub DictionaryFilter()
Dim TT As Double
TT = Timer

Dim Dic As Object
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
Set Dic = CreateObject("Scripting.Dictionary")
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If Not Dic.Exists(sKey) Then
                j = j + 1
                Dic.Add sKey, j
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(Dic.Item(sKey), 4) = Result(Dic.Item(sKey), 4) + ArrData(i, 3)
            End If
        End If
    Next i
    If j > 0 Then
        .Range("H2").Resize(100, 4).ClearContents
        .Range("H2").Resize(j, 4) = Result
    End If
End With

MsgBox Round(Timer - TT, 2)  '0.26-0.28 giây'
End Sub
2. Ví dụ 2: So sánh tốc độ code khi Add Keys là kiểu số vào Hashtable và Dictionary (Hashtable và Dictionary đều nhận kiểu dữ liệu của Key là kiểu số).
Hashtable:
PHP:
Sub AddKeys_Hashtable()
    Dim TT As Double
    TT = Timer
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If HTbl.Containskey(i) = False Then
            HTbl.Add i, ""
        End If
    Next i
    Set HTbl = Nothing
    MsgBox Round(Timer - TT, 2) '0.19-0.20 giây'
End Sub
Dictionary:
PHP:
Sub AddKeys_Dictionary()
    Dim TT As Double
    TT = Timer
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If Dic.Exists(i) = False Then
            Dic.Add i, ""
        End If
    Next i
    Set Dic = Nothing
    MsgBox Round(Timer - TT, 2) '5.96-6.09 giây'
End Sub
 
Upvote 0
thấy cái Hashtable trên GPE ít người xài lắm ... hình như lần đầu tiên Mình thấy

Sao bạn biết nhiều thư viện hay vậy ... học ở mô đó chỉ Mạnh với he ...........:D
 
Upvote 0
thấy cái Hashtable trên GPE ít người xài lắm ... hình như lần đầu tiên Mình thấy

Bởi vì nó nằm trong thư viện của .Net; mà .Net thì không quan trọng lắm đối với Excel
Ở GPE này, nhu cầu lập bảng đối chiếu, tức là sức mạnh của bảng băm gần như không có.
Ngược lại, gần như 99,9% các ứng dụng viết ở GPE là để lọc giá trị duy nhất. Sử dụng Dictionary dủ rồi, vừa dễ hơn, vừa thích nghi hơn với nhiều hệ thống cũ.

(thực ra mới đay có mọt bài đúng là có thể thử sức bảng băm. Tôi khong trả lời cho bài ấy vì lý do riêng của tôi. Nhưng chủ thớt có thể thử theo gợi ý này)
 
Upvote 0
Bởi vì nó nằm trong thư viện của .Net; mà .Net thì không quan trọng lắm đối với Excel
Ở GPE này, nhu cầu lập bảng đối chiếu, tức là sức mạnh của bảng băm gần như không có.
Ngược lại, gần như 99,9% các ứng dụng viết ở GPE là để lọc giá trị duy nhất. Sử dụng Dictionary dủ rồi, vừa dễ hơn, vừa thích nghi hơn với nhiều hệ thống cũ.

(thực ra mới đay có mọt bài đúng là có thể thử sức bảng băm. Tôi khong trả lời cho bài ấy vì lý do riêng của tôi. Nhưng chủ thớt có thể thử theo gợi ý này)
Vậy ứng dụng Hashtable trong những trường họp nào có liên quan tới Excel ... Mong bạn chỉ sơ qua một chút ... để mình có thể hình dung ra nó như thế nào

Xin cảm ơn
 
Upvote 0
Scripting.Dictionary vốn có sẵn trong Windows và được dùng bởi VBScript nghĩa là không cần cài Office thì Scripting.Dictionary đã thành viên của Windows rồi. Tương tự Netframework được cài sẵn trong Windows 7 (Windows 8 với 10 thì tôi mới đi cài dùm nên chưa biết :D) nên NetFramework cũng là thành phần của Windows nhưng nó tân tiến hơn.

Làm một phép so sánh hiệu năng giữa Hashtable của NetFramework với Dictionary của Scripting thực sự rất thú vị vì nhờ đó người đọc có thể tiếp cận được những công nghệ mới và có sự lựa chọn tốt nhất. Tuy nhiên tôi có hơi thắc mắc là sao không có phép so sánh hiệu năng Dictionary giữa NetFrameWork với Scripting. Vì đem HashTable đấu với Dictionary thì có vẻ không cùng hạng cân.

Cuối cùng nếu có lỗi ngữ pháp với từ ngữ tôi dùng ở đây thì vui lòng xem là "vô nghĩa" (miễn bàn luôn) để tránh lắm lời nhé. :D
 
Lần chỉnh sửa cuối:
Upvote 0
Scripting.Dictionary vốn có sẵn trong Windows và được dùng bởi VBScript nghĩa là không cần cài Office thì Scripting.Dictionary đã thành viên của Windows rồi. Tương tự Netframework được cài sẵn trong Windows 7 (Windows 8 với 10 thì tôi mới đi cài dùm nên chưa biết :D) nên NetFramework cũng là thành phần của Windows nhưng nó tân tiến hơn.

Làm một phép so sánh hiệu năng giữa Hashtable của Net với Dictionary của Scripting thực sự rất thú vị vì nhờ đó người đọc có thể tiếp cận được những công nghệ mới và có sự lựa chọn tốt nhất. Tuy nhiên tôi có hơi thắc mắc là sao không có phép so sánh hiệu năng Dictionary giữa NetFrameWork với Scripting. Vì đem Hash đấu với Dictionary thì có vẻ không cùng hạng cân.

Cuối cùng nếu có lỗi ngữ pháp với từ ngữ tôi dùng ở đây thì vui lòng xem là "vô nghĩa" (miễn bàn luôn) để tránh lắm lời nhé. :D
Bạn có VD nào điển hình kèm code úp cho mình học với ... nói vậy nghe biết vậy chứ ..... ko biết cụ thể nó là gì luôn .......... nghe ngáo ngơ như vịt nghe sấm vậy ,,,,,,,
 
Upvote 0
Bạn có VD nào điển hình kèm code úp cho mình học với ... nói vậy nghe biết vậy chứ ..... ko biết cụ thể nó là gì luôn .......... nghe ngáo ngơ như vịt nghe sấm vậy ,,,,,,,
Tôi không chuyên về VBA nên chắc không giúp gì được rồi. Tại mấy bữa xem Dictionary trong C# tôi thấy người ta đề cập đến HashTable nên ám thị luôn. Giờ đụng chữ Hashtable nên góp vài ý tưởng vui vẻ thôi chứ viết code tôi toàn phải tham khảo ví dụ không hà chứ không nắm đượcc cái gì ráo trọi. :)

Tôi đang tham khảo code bên địa chỉ này nè, dựa vô đấy cộng thêm ví dụ ở trên với trình của kieu manh dư sức xoay được thôi. Dictionary của 2 nền tảng này khá tương đồng dù có thể dùng từ ngữ khác nhau tý (nhưng hay là 2 thằng đó ko lên lớp nhau về cách dùng từ :D) .
 
Lần chỉnh sửa cuối:
Upvote 0
Ngày xưa, khi Microsoft ra ngón ASP thì các trang quép này được viết bằng ngôn ngữ VBScript, hay JScript (một phiên bản JavaScript của Microsoft)
Microsoft cải tiến luôn cái Dictinary để dùng chung trong hệ thóng, và đặt nó trong thư viên Script Hosting

Về sau này, Microsoft ra thêm cái nền tảng .Net (hình như hồi xưa nó viết là .NET, về sau này thì có viết hoa hay không cũng chẳng sao). Kỹ thuật ASP được thay thế bởi ASPX, tức là asp.Net; code viết trên ngôn ngữ C# hoặc VB.Net. Microsoft bị cạnh tranh rất dữ dội về nhiều mặt (điển hình là PHP) cho nên đổ rất nhiều nổ lực vào .Net
Thay vì dùng chính sách có chi dùng nấy nửa mùa của VBA; .Net được viết lại hoàn chỉnh và cải tiến đều đặn. Lưu ý rằng C# và VB.Net là ngôn ngữ được thiết lập để ứng dụng hướng đối tượng, trong khi VBA và VBScript chỉ là ngôn ngữ cấu trúc, được nới thêm ra để hổ trợ kết nối các đối tượng.

Hashtable của .Net là cái class (lưy ý: ngôn ngữ hướng đối tượng) xây theo cấu trúc Associative Array của lý thuyết lập trình - khái niệm Associative Array rộng rãi hơn cho nên cấu trúc này có thể mạnh hơn.

Tóm lại, Hashtable có thể làm được một vài việc mà Dictionary bị giới hạn. Tuy nhiên, những giới hạn này hầu như khong xảy ra với VBA. Hashtable tân tiến hơn cho nên giải thuật băm của nó cũng cao hơn và được cải tiến đều đặn. Mặt khác, Dictionary cổ điển hơn cho nên dễ sử dụng hơn.

Chú thích: tôi dùng từ "class" phân biệt với "đối tượng" ở đây chỉ với mục đích phân biệt 1 vài tính chất.
Các ngôn ngữ hướng đối tượng có thể thừa kế class, điển hình là C# có thể viết thêm phương thức nới rộng (extension method) cho class.
Các ngôn ngữ cấu trúc (như VBA) chỉ có thể dựng đối tượng và sử dụng theo kiểu có gì xài nấy.

Chú thích 2: nếu cần so sánh thì các bạn nên so sánh Dictionary và Collection. Bởi vì 2 cái này quan trọng hơn đối với VBA.
 
Upvote 0
Bạn có VD nào điển hình kèm code úp cho mình học với ... nói vậy nghe biết vậy chứ ..... ko biết cụ thể nó là gì luôn .......... nghe ngáo ngơ như vịt nghe sấm vậy ,,,,,,,
À đây! Tôi mới tìm được cái link hướng dẫn dùng Dictionary bằng VBNet đây. Mới mò vô mắt nhắm mắt mở mà tôi cứ tưởng là xem ví dụ về Dic trong VBA luôn đấy :D. Chắc là xem xong dễ hiểu hơn nhiều so với code bằng C#.

Cơ mà thấy bối rối với cách chia ngôi của mấy động từ của Microsoft đã Add, Remove nguyên mẫu tự dưng có ContainsValue chứ hổng phải là ContainValue. Rồi bỏ đi s nên có TryGetValue chứ hổng phải TriesGetValue. Thêm luôn cái WriteLine chứ hổng phải WritesLine. Cộng với ToDictionary (theo từ điển là...) nếu mà dựa vô ngữ pháp tôi học thì càng khó hiểu (cũng không đến nỗi "vô nghĩa") ;)

Luận theo ngữ pháp, chắc chỉ mấy bác siêu tiếng Anh là hiểu nổi cách dùng chữ của Microsoft chứ ngu như tôi là bó tay luôn:D
 
Lần chỉnh sửa cuối:
Upvote 0
"Contains" hôm trước được anh VetMini giải thích.
Chỗ "TryGetValue" có vẻ lạ... Chắc đợi anh VetMini vào giải đáp tiếp. :)

Chúc cả nhà ngày vui! :)
 
Upvote 0
Để cho bài viết của chủ topic được trọn vẹn, liệu chúng ta có nên bàn mọi thứ (dù là "trong lề" hay "ngoài lề") ở một topic khác không?
 
Upvote 0
"Contains" hôm trước được anh VetMini giải thích.
Chỗ "TryGetValue" có vẻ lạ... Chắc đợi anh VetMini vào giải đáp tiếp. :)

Contains là một trạng thái: A contains B, hay B is contained within A. Trạng thái này đại khái có thể coi như là một thuộc tính
TryGetValue là một mệnh lệnh: try get value [x] for me. Try this, try that... Mệnh lệnh thì dùng động từ nguyên mẫu, văn phạm Anh như vậy. (thể của get thì là một vấn đề khác, thường là getting, nhưng bỏ đó cho gọn cũng không sao)

Để cho bài viết của chủ topic được trọn vẹn, liệu chúng ta có nên bàn mọi thứ (dù là "trong lề" hay "ngoài lề") ở một topic khác không?

Không sao đâu bạn. Ngừoi khác có thể coi như là mọt cuộc tranh luận. Nhưng với tôi chỉ là mọt dịp để trau giồi Anh ngữ. Khong có mấy dịp. Và tôi có lưu ý lời của bạn nên chỉ giải thích trực tiếp, không dây dưa.
Đương nhiên là nếu nó có khả năng kéo dài thì nên cắt đi.
 
Lần chỉnh sửa cuối:
Upvote 0
Dạ chào anh, Em là thành viên mới, em cảm ơn anh về bài viết, anh có thế cho em list bài học từ đầu của anh được không ạ.
 
Upvote 0
Contains là một trạng thái: A contains B, hay B is contained within A. Trạng thái này đại khái có thể coi như là một thuộc tính
Nếu dùng như vậy nghĩa là khẳng định luôn là có chứa Key nào đó. Giả sử không chứa key đó thì sao? Còn một cái khó hiểu nữa là tại sao Microsoft lại dùng từ ToDictionary? Cứ theo ngữ pháp sẽ hiểu là "Theo từ điển thì..." hoặc là "vô nghĩa" vì "To" vốn là từ phụ trợ hơn là có nghĩa cụ thể? Xin lỗi nếu em đã hỏi câu quá ngu.:( Nhưng nếu mà thông suốt được vấn đề thì về sau em sẽ ít phải dùng những từ bị lưu ý là "vô nghĩa" nữa.:D
 
Lần chỉnh sửa cuối:
Upvote 0
Bài ví dụ cụ thể áp dụng Hashtable.

1. Ví dụ 1: Lọc loại trùng và tính tổng số lượng ứng với mã sau khi lọc loại trùng.
Xét vùng dữ liệu 100,000 dòng (xem trong file đính kèm ở ngay bài trên).
Sử dụng Hashtable và Dictionay để so sánh.
Hashtable:
PHP:
Sub HashtableFilter()
Dim TT As Double
TT = Timer
Dim HTbl As Object
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
Set HTbl = CreateObject("System.Collections.Hashtable")
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If HTbl.Containskey(sKey) = False Then
                j = j + 1
                HTbl.Add sKey, j
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(HTbl.Item(sKey), 4) = Result(HTbl.Item(sKey), 4) + ArrData(i, 3)
             End If
        End If
    Next i
    If j > 0 Then
        .Range("M2").Resize(100, 4).ClearContents
        .Range("M2").Resize(j, 4) = Result
    End If
End With

MsgBox Round(Timer - TT, 2) '1.62-1.66 giây'
End Sub
Dictionay:
PHP:
Sub DictionaryFilter()
Dim TT As Double
TT = Timer

Dim Dic As Object
Dim i As Long, lRow As Long, ArrData(), Result(), sKey As String, j As Long
Set Dic = CreateObject("Scripting.Dictionary")
With Sheet1
    lRow = .Range("B" & Rows.Count).End(xlUp).Row
    ArrData = .Range("B2:D" & lRow).Value2
    lRow = UBound(ArrData, 1)
    ReDim Result(1 To lRow, 1 To 4)
    For i = 1 To lRow
        sKey = ArrData(i, 1)
        If sKey <> "" Then
            If Not Dic.Exists(sKey) Then
                j = j + 1
                Dic.Add sKey, j
                Result(j, 1) = j
                Result(j, 2) = sKey
                Result(j, 3) = ArrData(i, 2)
                Result(j, 4) = ArrData(i, 3)
            Else
                Result(Dic.Item(sKey), 4) = Result(Dic.Item(sKey), 4) + ArrData(i, 3)
            End If
        End If
    Next i
    If j > 0 Then
        .Range("H2").Resize(100, 4).ClearContents
        .Range("H2").Resize(j, 4) = Result
    End If
End With

MsgBox Round(Timer - TT, 2)  '0.26-0.28 giây'
End Sub
2. Ví dụ 2: So sánh tốc độ code khi Add Keys là kiểu số vào Hashtable và Dictionary (Hashtable và Dictionary đều nhận kiểu dữ liệu của Key là kiểu số).
Hashtable:
PHP:
Sub AddKeys_Hashtable()
    Dim TT As Double
    TT = Timer
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If HTbl.Containskey(i) = False Then
            HTbl.Add i, ""
        End If
    Next i
    Set HTbl = Nothing
    MsgBox Round(Timer - TT, 2) '0.19-0.20 giây'
End Sub
Dictionary:
PHP:
Sub AddKeys_Dictionary()
    Dim TT As Double
    TT = Timer
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If Dic.Exists(i) = False Then
            Dic.Add i, ""
        End If
    Next i
    Set Dic = Nothing
    MsgBox Round(Timer - TT, 2) '5.96-6.09 giây'
End Sub
Như vậy có nghĩa là nếu key là kiểu số thì Hashtable sẽ sử lý nhanh hơn nhiều lần phải không mọi người?
 
Upvote 0
2. Ví dụ 2: So sánh tốc độ code khi Add Keys là kiểu số vào Hashtable và Dictionary (Hashtable và Dictionary đều nhận kiểu dữ liệu của Key là kiểu số).
Hashtable:
PHP:
Sub AddKeys_Hashtable()
    Dim TT As Double
    TT = Timer
    Dim HTbl As Object
    Set HTbl = CreateObject("System.Collections.Hashtable")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If HTbl.Containskey(i) = False Then
            HTbl.Add i, ""
        End If
    Next i
    Set HTbl = Nothing
    MsgBox Round(Timer - TT, 2) '0.19-0.20 giây'
End Sub
Dictionary:
PHP:
Sub AddKeys_Dictionary()
    Dim TT As Double
    TT = Timer
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If Dic.Exists(i) = False Then
            Dic.Add i, ""
        End If
    Next i
    Set Dic = Nothing
    MsgBox Round(Timer - TT, 2) '5.96-6.09 giây'
End Sub
Sao bạn không làm thêm trường hợp so sánh khi thêm key ở dạng chuỗi? Tức thay cho Add số, "" thì Add Cstr(số), ""?

Nếu so sánh tốc độ thì bạn thử sửa thành (AddKeys_Hashtable giữ nguyên)
Mã:
Sub AddKeys_Dictionary()
    Dim TT As Double
    TT = Timer
    Dim Dic As Object
    Set Dic = CreateObject("Scripting.Dictionary")
    Dim x As Long, y As Long, i As Long
    x = 1000000000
    y = 1000020000
    For i = x To y
        If Dic.Exists(CStr(i)) = False Then
            Dic.Add CStr(i), ""
        End If
    Next i
    Set Dic = Nothing
    Debug.Print "dic " & Round(Timer - TT, 2)
End Sub
Kết quả ngược lại? Là dic nhanh hơn Hashtable vài lần?
Nếu vẫn giữ nguyên x và y nhưng ở cả 2 sub đều dùng CStr(i) thì dic cũng vẫn nhanh hơn vài lần

Hoặc vẫn giữ nguyên như cũ, tức thêm key ở dạng số nhưng ở cả 2 Sub đổi thành
Mã:
x = 9900000
y = 9920000
Tốc độ của dic vẫn nhanh hơn vài lần?

Với dic thì (kết luận từ quan sát thôi):
1. Với key có <= 8 ký tự hay > 8 ký tự thì thêm key ở dạng chuỗi tốc độ hầu như không thay đổi mấy, coi như nhau.
2. Thêm key ở dạng số có 7 hoặc < 7 ký tự: tốc độ gần như thêm ở dạng chuỗi.
3. Thêm key ở dạng số có 8 hoặc > 8 ký tự (> 9999999, < -9999999): tốc độ chậm hơn rất nhiều so với thêm ở dạng chuỗi.

Nguyên nhận thì theo tôi nghĩ do cái giải thuật băm của dic, dù tôi không chắc đã hiểu ý bạn VetMini nói gì khi viết giải thuật băm
 
Lần chỉnh sửa cuối:
Upvote 0
Như vậy có nghĩa là nếu key là kiểu số thì Hashtable sẽ sử lý nhanh hơn nhiều lần phải không mọi người?
Không hẳn thế. Trong Sub AddKeys_Hashtable và Sub AddKeys_Dictionary bạn thử đổi thành
Mã:
x = 9900000
y = 9920000
rồi so sánh tốc độ.

Tất nhiên tốc độ chỉ quan trọng khi cần thêm nhiều giá trị, cỡ hàng ngàn. Nhưng lúc đó cần xét xem thường thì trong thực tế ta làm việc với hàng ngàn số cỡ lớn hay hàng ngàn số cỡ bình thường.
 
Upvote 0
Sao bạn không làm thêm trường hợp so sánh khi thêm key ở dạng chuỗi? Tức thay cho Add số, "" thì Add Cstr(số), ""?
Vâng anh.
Em nêu ví dụ đó mới ứng với trường hợp thứ 3 anh giải thích ở trên:
"3. Thêm key ở dạng số có 8 hoặc > 8 ký tự (> 9999999, < -9999999): tốc độ chậm hơn rất nhiều so với thêm ở dạng chuỗi."

Lý do: Lúc em soạn bài này thì có một topic hỏi về việc Add dạng số có nhiều hơn 8 ký tự (ở bài này) nên em làm một ví dụ cho trường hợp đó.

Ba mục ở phần kết luận trên cũng tốn không ít thời gian thử nghiệm...

Cảm ơn anh.
Chúc anh ngày vui!
 
Upvote 0
Web KT
Back
Top Bottom